package com.lsa.letcode.the8.atoi;

public class Solution {
    public int atoi(String str) {
    	int res = 0;
    	int s = 0; // state
    	boolean isNegative = false;
    	for (int i = 0; i < str.length(); i++) {
    		char c = str.charAt(i);
    		if (s == 0) {
    			if (Character.isDigit(c)) {
    				int d = c - '0';
    				if (isNegative) {
						d = -d;
					}
    				res = d;
    				s = 1;
    			}
    			else {
    				if (c == '-') {
    					isNegative = true;
    					s = 1;
    				}
    				else if ( c == '+' ) {
    					s = 1;
    				}
    				else if (Character.isWhitespace(c)) {
    					// skip
    				}
    				else {
    					return 0;
    				}
    			}
    		}
    		else if (s == 1) {
    			if (Character.isDigit(c)) {
    				try{
    					int d = c - '0';
    					if (isNegative) {
    						d = -d;
    					}
						res = add(mul(res , 10), d);
    				}
    				catch(ArithmeticException e) {
    					return isNegative? Integer.MIN_VALUE : Integer.MAX_VALUE;
    				}
    			}
    			else {
    				break;
    			}
    		}
		}
        return res;
    }
    
    private static int mul(int a, int b) {
    	checkMulOverflow(a, b);
		return a * b;
	}
    
    private static void checkMulOverflow(int a, int b) {
    	boolean isOverflow = false;
    	if (a > 0 && b > 0 || a < 0 && b < 0) {
    		if (a > Integer.MAX_VALUE / b) {
    			isOverflow = true;
    		}
    	}
    	else {
    		if (a < Integer.MIN_VALUE / b) {
    			isOverflow = true;
    		}
    	}
    	if (isOverflow) {
    		throw new ArithmeticException();
    	}
    }
	
	private static int add(int a, int b) {
		checkAddOverflow(a, b);
		
		return a + b;
	}
	
	private static void checkAddOverflow(int a, int b) {
    	boolean isOverflow = false;
    	if (((a > 0 && b > 0) && a > Integer.MAX_VALUE - b) || ((a < 0 && b < 0) && a < Integer.MIN_VALUE - b)) {
			isOverflow = true;
		}
    	
    	if (isOverflow) {
    		throw new ArithmeticException();
    	}
    }
}